Skip to content

Turnkey fresh-worktree dev env: atomic per-checkout e2e ports, bootstrap, leak reaper#973

Merged
RhysSullivan merged 4 commits into
mainfrom
claude/gracious-satoshi-42e8e9
Jun 12, 2026
Merged

Turnkey fresh-worktree dev env: atomic per-checkout e2e ports, bootstrap, leak reaper#973
RhysSullivan merged 4 commits into
mainfrom
claude/gracious-satoshi-42e8e9

Conversation

@RhysSullivan

@RhysSullivan RhysSullivan commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

Why

Running the e2e suite from a fresh worktree failed 31/78 cloud scenarios with misleading auth errors ("AuthKit emulator did not redirect (403)", "No organization in session"). Root cause: every checkout shared the same default ports (4798/4799/...), a leaked vite dev server from another checkout was squatting 4798, vite's --strictPort exit was swallowed by the boot glue, and waitForHttp silently attached to the foreign checkout's server. Fresh worktrees also start with empty vendor submodules and unbuilt internal packages, so the first dev-server boot dies with "Failed to resolve entry for package '@executor-js/vite-plugin'".

What

Atomic per-checkout port claiming (e2e/src/ports.ts)

  • Each checkout hashes its repo root to a preferred block of 10 ports (42000–45999).
  • At boot, claimPorts binds the block's reserved lock port (held for the suite's lifetime — two racing suites can't both win), probes the rest for squatters, and walks forward block-by-block until it owns a fully free block.
  • Claimed ports are published via E2E_*_PORT env so vitest workers (spawned after globalsetup) agree; explicit env pins skip claiming, E2E_<TARGET>_URL still attaches to a running instance.
  • Verified by squatting the preferred block and watching the suite relocate one block over and pass.

One-command setup (bun run bootstrap)

  • Idempotent: vendor submodules + bun install (prepare hook builds the packages dev servers need) + Playwright chromium. Validated from a cold worktree straight to a green suite.

Leak cleanup + run digest

  • bun run reap lists leaked dev stacks, kills orphans whose checkout is gone (--all for the rest).
  • cd e2e && bun run ports prints the preferred block; bun run summary digests runs/*/result.json into pass/fail counts.

Test fix

Docs

  • AGENTS.md: fresh-checkout setup section + environment gotchas; e2e/AGENTS.md: port-claiming behavior.

Validation

  • Full suite green from this worktree and from a second cold-bootstrapped worktree running concurrently (each on its own block).
  • Collision drill: with the preferred block's lock + selfhost port squatted, the suite logged the move and passed 17/17 one block over.
  • format:check, lint, e2e typecheck pass.

Two pre-existing under-load flakes surfaced during full runs (auth-methods tool_not_found race, connect-handoff modal timeout); both pass in isolation and are unrelated to this change.

Stack

  1. Turnkey fresh-worktree dev env: atomic per-checkout e2e ports, bootstrap, leak reaper #973 👈 current
  2. Agent evidence workflow: principles docs, e2e dev CLI, typed emulator client #977

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 12, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
executor-marketing ad84e39 Commit Preview URL

Branch Preview URL
Jun 12 2026, 04:32 PM

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 12, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
executor-cloud ad84e39 Jun 12 2026, 04:35 PM

@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Cloudflare preview

Torn down — the PR is closed.

@pkg-pr-new

pkg-pr-new Bot commented Jun 12, 2026

Copy link
Copy Markdown

Open in StackBlitz

@executor-js/cli

npm i https://pkg.pr.new/@executor-js/cli@973

@executor-js/config

npm i https://pkg.pr.new/@executor-js/config@973

@executor-js/execution

npm i https://pkg.pr.new/@executor-js/execution@973

@executor-js/sdk

npm i https://pkg.pr.new/@executor-js/sdk@973

@executor-js/codemode-core

npm i https://pkg.pr.new/@executor-js/codemode-core@973

@executor-js/runtime-quickjs

npm i https://pkg.pr.new/@executor-js/runtime-quickjs@973

@executor-js/plugin-file-secrets

npm i https://pkg.pr.new/@executor-js/plugin-file-secrets@973

@executor-js/plugin-graphql

npm i https://pkg.pr.new/@executor-js/plugin-graphql@973

@executor-js/plugin-keychain

npm i https://pkg.pr.new/@executor-js/plugin-keychain@973

@executor-js/plugin-mcp

npm i https://pkg.pr.new/@executor-js/plugin-mcp@973

@executor-js/plugin-onepassword

npm i https://pkg.pr.new/@executor-js/plugin-onepassword@973

@executor-js/plugin-openapi

npm i https://pkg.pr.new/@executor-js/plugin-openapi@973

executor

npm i https://pkg.pr.new/executor@973

commit: ad84e39

…fast, bootstrap script

- e2e ports are now derived from a hash of the checkout root (42000-45999
  blocks) so concurrent worktrees never collide; E2E_*_PORT/URL still override.
- globalsetups fail fast with the squatting PID when a port is taken instead
  of silently attaching to a foreign checkout's dev server (the cause of
  31-scenario auth-error cascades).
- scripts/bootstrap.ts: one idempotent command for submodules + install +
  playwright; scripts/reap-dev-servers.ts kills orphaned dev stacks.
- e2e: bun run ports prints this checkout's derived ports.
- sources-api scenario: align with payload-first OpenAPI results (PR #956
  changed the product, the cloud-only scenario was not updated).
- AGENTS.md: fresh-worktree setup + environment gotchas (fish shell, /tmp
  scripts, bun.lock conflicts, per-checkout ports).
The hash-derived block was only collision-unlikely (28 checkouts over 400
blocks is birthday-paradox territory), and probe-then-bind raced. Each block
now reserves its last port as a lock held for the suite's lifetime: claimPorts
binds the lock (atomic — two racing suites can't both win), probes the
remaining ports for squatters, and walks forward block-by-block until it owns
a fully free block, publishing the claimed ports via E2E_*_PORT env so test
workers agree. Explicit env pins skip claiming entirely. Verified by squatting
the preferred block's lock+selfhost ports and watching the suite relocate one
block over and pass 17/17.
Nothing imports from vendor/ at runtime — the forks are consumed as
published npm packages (vendor/README.md is explicit). Forcing the
submodule init in bootstrap taught every fresh worktree a false
dependency. --forks remains for deliberately developing a fork.
@RhysSullivan RhysSullivan force-pushed the claude/gracious-satoshi-42e8e9 branch from f709965 to ad84e39 Compare June 12, 2026 16:30
@RhysSullivan RhysSullivan marked this pull request as ready for review June 12, 2026 16:31
@RhysSullivan RhysSullivan merged commit 2ae9f50 into main Jun 12, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant